#pragma once

#include <iostream>
#include <string>
#include <sys/types.h>
#include <sys/socket.h>

//工具类
class Util{
    public:
        /*
         * 1.从tcp的接收缓冲取当中按照1个字节1个字节读取
         * 2.循环读取的时候， 判断是否是\n, 如果不是继续读取
         * 3.将读取到的有效字符放到string对象当中
         *
         * 参数：
         *   sock ： 新连接套接字
         *   out ： 出参， 返回给调用者读到的一行内容
         *
         * 返回值：
         *    >0: 读到内容了，且返回读到的字符个数
         *    ==0： 对端关闭连接
         *    -1：接收失败了
         * */
        static int ReadLine(int sock, std::string &out){
            char ch = 'X';
            while(ch != '\n'){
                ssize_t s = recv(sock, &ch, 1, 0);
                if(s > 0){
                    if(ch == '\r'){
                        /*
                         * MSG_PEEK 是窥探接收， 并没有从缓冲区当中将字符读走
                         * */
                        recv(sock, &ch, 1, MSG_PEEK);
                        //如果是\n， 则说明当前行接收完毕
                        if(ch == '\n'){
                            //把\r\n->\n
                            //窥探成功，这个字符一定存在
                            recv(sock, &ch, 1, 0);
                        }else{
                            //如果不是\n, 则说明http的请求格式是按照\r进行间隔的
                            //为了后续处理方便， 我们把接收的\r改成\n,放到字符串的后面
                            ch = '\n';
                        }
                    }
                    //1. 普通字符
                    //2. \n
                    out.push_back(ch);
                }
                else if(s == 0){
                    //对端关闭连接
                    return 0;
                }
                else{
                    //接收失败
                    return -1;
                }
            }
            return out.size();
        }


        /*
         * 该函数将请求体当中的行的key:value进行切分
         * target就是待要切割的字符串， 也就是请求体当中的某一行
         * key放到sub1_out
         * value放到sub2_out
         * 切分的分割符是":"
         * */
        static bool CutString(const std::string &target, std::string &sub1_out, std::string &sub2_out, std::string sep){
            //查找sep的位置， 一般就是seq传递进行的是":" 
            size_t pos = target.find(sep);
            //std::string::npos是一个常数，它等于size_type类型可以表示的最大值，用来表示一个不存在的位置,类型一般是std::container_type::size_type
            if(pos != std::string::npos){
                sub1_out = target.substr(0, pos);
                sub2_out = target.substr(pos+sep.size());
                return true;
            }
            return false;
        }
};
